package com.atguigu.gmall.order.Service.Impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.Service.OrderInfoService;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: gmall-parent
 * @author: Mr.Zhuo
 * @create: 2022-04-16 15:03
 **/
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${ware.url}")
    private String WARE_URL;


    /**
     * 保存订单
     *
     * @param orderInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrder(OrderInfo orderInfo) {

        // 进行分别数据保存
        orderInfo.sumTotalAmount();
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        orderInfo.setCreateTime(new Date());

        // 设置订单操作时间
        orderInfo.setOperateTime(new Date());

        // 设置订单过期时间
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, 1);
        orderInfo.setExpireTime(instance.getTime());

        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        // 获取订单明细
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuffer tradeBody = new StringBuffer();
        for (OrderDetail orderDetail : orderDetailList) {
            tradeBody.append(orderDetail.getSkuName() + " ");
        }
        if (tradeBody.toString().length() > 100) {
            orderInfo.setTradeBody(tradeBody.toString().substring(0, 100));
        } else {
            orderInfo.setTradeBody(tradeBody.toString());
        }

        orderInfoMapper.insert(orderInfo);

        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }
        //发送延迟队列，如果定时未支付，取消订单
        rabbitService.sendDelayed
                (MqConst.EXCHANGE_DIRECT_ORDER_CANCEL, MqConst.ROUTING_ORDER_CANCEL, orderInfo.getId(), MqConst.DELAY_TIME);


        // 保存完订单之后，我们需要进行发送消息
        return orderInfo.getId();

    }

    /**
     * 生成一个随机的tradeNo 并保存在redis
     *
     * @param userId
     * @return
     */
    @Override
    public String getTradeNo(String userId) {
        String tradeNo = UUID.randomUUID().toString();

        // 保存到redis中
        redisTemplate.opsForValue().set("tradeNo:" + userId, tradeNo);

        return tradeNo;
    }

    /**
     * 比较tradeNo
     *
     * @param tradeNo
     * @param userId
     * @return
     */
    @Override
    public Boolean compareTradeNo(String tradeNo, String userId) {

        // 获取存在redis中的数据
        String tradeNoRe = (String) redisTemplate.opsForValue().get("tradeNo:" + userId);

        // 返回比较结果
        return tradeNo.equals(tradeNoRe);
    }

    /**
     * 删除对应用户的tradeNo
     *
     * @param userId
     */
    @Override
    public void delTradeNo(String userId) {
        redisTemplate.delete("tradeNo:" + userId);
    }


    /**
     * 调用库存管理系统
     *
     * @param skuId
     * @param skuNum
     * @return
     */
    @Override
    public Boolean checkStock(Long skuId, Integer skuNum) {
        // 远程调用http://localhost:9001/hasStock?skuId=10221&num=2
        String result = HttpClientUtil.doGet(WARE_URL + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        return "1".equals(result);

    }

    /**
     * 查询我的订单
     *
     * @param page
     * @param userId
     * @return
     */
    @Override
    public IPage<OrderInfo> indexOrderInfo(Page<OrderInfo> page, String userId) {

        IPage<OrderInfo> infoIPage = orderInfoMapper.selectPageUnion(page, userId);

        // 做一个细节处理
        List<OrderInfo> records = infoIPage.getRecords();

        List<OrderInfo> collect = records.stream().map(orderInfo -> {
            String orderStatus = orderInfo.getOrderStatus();
            String statusNameByStatus = OrderStatus.getStatusNameByStatus(orderStatus);
            orderInfo.setOrderStatusName(statusNameByStatus);
            return orderInfo;
        }).collect(Collectors.toList());
        infoIPage.setRecords(collect);
        return infoIPage;
    }

    /**
     * 拆单
     *
     * @param orderId
     * @param wareSkuMap
     * @return
     */
    @Override
    public List<OrderInfo> splitOrder(String orderId, String wareSkuMap) {
        // 首先获取数据库生成的订单
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);

        QueryWrapper<OrderDetail> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", orderId);
        List<OrderDetail> orderDetailsDb = orderDetailMapper.selectList(wrapper);
        orderInfo.setOrderDetailList(orderDetailsDb);
        List<OrderInfo> infoList = new ArrayList<>();

        // 将wareSkuMap转换成map
        List<Map> mapList = JSON.parseArray(wareSkuMap, Map.class);
        if (mapList != null) {
            for (Map map : mapList) {
                String wareId = (String) map.get("wareId");

                List<String> skuIds = (List<String>) map.get("skuIds");

                OrderInfo splitOrderInfo = new OrderInfo();
                // 进行属性复制
                BeanUtils.copyProperties(orderInfo, splitOrderInfo);

                // 其他属性赋值
                // 防止外键冲突
                splitOrderInfo.setId(null);
                // 父订单
                splitOrderInfo.setParentOrderId(orderInfo.getId());
                // 仓库id
                splitOrderInfo.setWareId(wareId);

                // 进行订单明细赋值
                ArrayList<OrderDetail> splitOrderDetails = new ArrayList<>();
                List<OrderDetail> orderDetails = orderInfo.getOrderDetailList();
                for (OrderDetail orderDetail : orderDetails) {
                    for (String skuId : skuIds) {
                        if (orderDetail.getSkuId() == Long.parseLong(skuId)) {
                            splitOrderDetails.add(orderDetail);
                        }
                    }
                }
                splitOrderInfo.setOrderDetailList(splitOrderDetails);
                // 总价格获取
                splitOrderInfo.sumTotalAmount();
                infoList.add(splitOrderInfo);
                // 然后进行存储子订单
                orderInfoMapper.insert(splitOrderInfo);
            }

            // 修改原始订单状态
            updateOrderStatus(Long.parseLong(orderId), ProcessStatus.SPLIT);

            return infoList;
        }
        return null;
    }

    /**
     * 给仓库发送订单已支付，请发货
     *
     * @param orderId
     */
    @Override
    public void sendOrderStatus(Long orderId) {


        // 查询出来订单
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);

        // 首先更改订单状态
        updateOrderStatus(orderId, ProcessStatus.NOTIFIED_WARE);
        orderInfoMapper.updateById(orderInfo);
        // 转换成map
        String wareJson = initWareOrder(orderId);

        // 给仓库模块发送信息
        rabbitService.send(MqConst.EXCHANGE_DIRECT_WARE_STOCK, MqConst.ROUTING_WARE_STOCK, wareJson);
    }

    // 根据orderId 获取json 字符串
    private String initWareOrder(Long orderId) {
        // 通过orderId 获取orderInfo
        OrderInfo orderInfo = getOrderInfo(orderId);

        // 将orderInfo中部分数据转换为Map
        Map map = initWareOrder(orderInfo);

        return JSON.toJSONString(map);
    }


    /**
     * 将orderInfo中部分数据转换为Map
     *
     * @param orderInfo
     * @return
     */
    public Map initWareOrder(OrderInfo orderInfo) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2");
        map.put("wareId", orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！
    /*
    details:[{skuId:101,skuNum:1,skuName:
    ’小米手64G’},
    {skuId:201,skuNum:1,skuName:’索尼耳机’}]
     */
        //ArrayList<Map> mapArrayList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //for (OrderDetail orderDetail : orderDetailList) {
        //    HashMap<String, Object> orderDetailMap = new HashMap<>();
        //    orderDetailMap.put("skuId", orderDetail.getSkuId());
        //    orderDetailMap.put("skuNum", orderDetail.getSkuNum());
        //    orderDetailMap.put("skuName", orderDetail.getSkuName());
        //    mapArrayList.add(orderDetailMap);
        //}
        List<HashMap<String, Object>> collect = orderDetailList.stream().map(orderDetail -> {
            HashMap<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId", orderDetail.getSkuId());
            orderDetailMap.put("skuNum", orderDetail.getSkuNum());
            orderDetailMap.put("skuName", orderDetail.getSkuName());
            return orderDetailMap;
        }).collect(Collectors.toList());


        map.put("details", collect);
        return map;
    }


    /**
     * // 根据订单id获取数据
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);

        // 订单详情
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);

        List<OrderDetail> orderDetails = orderDetailMapper.selectList(queryWrapper);

        orderInfo.setOrderDetailList(orderDetails);

        return orderInfo;
    }

    /**
     * 取消订单的时候更改订单的  订单状态
     *
     * @param orderId
     */
    @Override
    public void execExpiredOrder(Long orderId) {
        updateOrderStatus(orderId, ProcessStatus.CLOSED);

        rabbitService.send(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
    }

    /**
     * 关闭订单
     *
     * @param orderId
     * @param s
     */
    @Override
    public void execExpiredOrder(Long orderId, String s) {
        updateOrderStatus(orderId, ProcessStatus.CLOSED);

        if ("2".equals(s)) {
            // 关闭支付订单
            rabbitService.send(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
        }
    }

    /**
     * 取消订单的时候更改订单的  订单状态
     *
     * @param orderId
     * @param processStatus
     */
    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setProcessStatus(processStatus.name());
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());

        orderInfoMapper.updateById(orderInfo);
    }

}
